有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中的递归素因子算法

我试图用java实现一个简单的算法,用于查找参数传递的整数的所有素数因子:

private static ArrayList<Integer> lstPrime= new ArrayList<Integer>();

    public static ArrayList primeFactors(int n) {

        if (isPrime(n)) 
        {
            lstPrime.add(n);
        }

        for (int i=2; i<=(Math.sqrt(n)); i++)
        {
            if (n % i == 0)
            {
                lstPrime.addAll(primeFactors(n/i));
                return lstPrime;
            }
        }
        return lstPrime;
    }

有趣的是,如果我通过81作为n,结果将是:3,3,3,3,3,3,3,3,而它应该是:3,3,3,3(3^4=81)


共 (6) 个答案

  1. # 1 楼答案

    public static void primeFactorsOf( int n )
        {
            int i = 2;
            boolean isFactor = false;
    
            if( isPrime( n ) )
                System.out.println( n+"." );
            else 
            {
                while( !isFactor )
                {
                    if( ( n % i == 0 ) && ( isPrime( i ) ) )
                    {
                        System.out.print( i +", " );
                        primeFactorsOf( n / i );
                        isFactor = true;
                    }
                    else
                        i ++;
                }
            }
        }
    
  2. # 2 楼答案

    好的!我想我已经解决了我的问题,除了ArrayList是在递归函数之外声明的。我无法想象其他任何处理列表的方法,因为这是一个递归函数,如果在函数中声明列表,那么每次递归发生时,它都会被一次又一次地实例化。以下是我到目前为止所做的,请随意批评:

    public static ArrayList<Integer> list = new ArrayList<Integer>();
    
    public static void primeFactors(int n) {
        if (isPrime(n)) 
        {
            list.add(n);
            return;
        }
    
        int i = 2;
        while (i < n/2)
        {
            if (n % i == 0)
            {
                 if (isPrime(i))
                 {
                     primeFactors(n/i);
                     list.add(i);
                     return;
                 } 
            }
            i++;
        }
        return;
    }
    

    例如,此代码将生成:3,3,3,3For primeFactors(81)5,3,2,2For primeFactors(60)等等

  3. # 3 楼答案

    问题在于递归实现。使用以下命令:

    public static ArrayList primeFactors(int n){
        if (isPrime(n))
        {
            list.add(n);
            return list;
        }
        int i = 1;
        while(true){
            if (n % (i+=2) == 0){
                if (isPrime(i))
                {
                    n = n / i;
                    list.add(i);
                    i = 1;
                }
            }
            if (i> Math.sqrt(n))
                break;
        }
        list.add(n);
        return list;
    }
    
  4. # 4 楼答案

    public static void primeFactorsOf( int n ) 
    {
        int i;
    
        if( isPrime( n ) )
            System.out.println( n +". " );
        else
        {
            for( i = 2; i < n; i ++ )
            {
                if( isPrime( i ) && n % i == 0 )
                {
                    System.out.print( i +", " );
                    n = n/i;
                    primeFactorsOf( n );
                }
            }
        }
    }
    
    public static boolean isPrime( int n )
    {
        int i;
    
        if( n < 2 )
            return false;
        else
        {
            for( i = 2; i < n; i += 1 )
            {
                if( n % i == 0 ) 
                    return false;
            }
        }    
    
        return true;
    }
    
  5. # 5 楼答案

    public static String soNguyenTo(int x, int i) {
        if (i == 1 && x > 1) {
            return "là số nguyen tố";
        }
        if (x == 0 || x % i == 0) {
            return "không phải là số nguyên tố";
        } else {
            return soNguyenTo(x, i - 1);
        }
    }
    
    public static void main(String[] args) {
        input = new Scanner(System.in);
        System.out.println("nhập số bất kỳ");
        int i = input.nextInt();
        System.out.println(i + ": " + soNguyenTo(i, (int) Math.sqrt(i)));
    
    }
    
  6. # 6 楼答案

    也许更复杂一点,但到目前为止它还可以工作,而且它使用的素数生成器可能是我在Java中能找到的最快(也是最小)的

    首先,我们得到了素数生成器,需要测试一个值是否为素数。我们使用一个生成器(这个生成器比原始方法快10倍),因此我们使用缓存列表:

    /**
     * Sieve of Sundaram prime number generator
     * Implementation following the Sieve of Sundaram to generate prime numbers 
     * 
     * @see http://en.wikipedia.org/wiki/Sieve_of_Sundaram
     */
    static public class SundaramSievePrimeGenerator {
       public String getName() { return "Sieve of Sundaram generator"; }
       public int[] findPrimes(int max) {
          int n = max/2;
          boolean[] isPrime = new boolean[max];
    
          Arrays.fill(isPrime, true);
    
          for (int i=1; i<n; i++) {
             for (int j=i; j<=(n-i)/(2*i+1); j++) {
                isPrime[i+j+2*i*j] = false;
             }
          }
    
          int[] primes = new int[max];
          int found = 0;
          if (max > 2) {
             primes[found++] = 2;
          }
          for (int i=1; i<n; i++) {
             if (isPrime[i]) {
                primes[found++] = i*2+1;
             }
          }
    
          return Arrays.copyOf(primes, found);
       }
    }
    

    然后我们需要两种方法来实际获取n的素因子列表:

    /**
     * Reuse an instance of the SundaramSievePrimeGenerator
     */
    static public List<Integer> findPrimeFactors(int n, SundaramSievePrimeGenerator g) {
       ArrayList<Integer> primeFactors = new ArrayList<Integer>();
    
       int[] primes = g.findPrimes(n+1);
       int v;
    
       // debug
       //System.out.print("** primes found : ");
       //for (int a : primes) {
       //   System.out.print(" " + a);
       //}
       //System.out.println();
    
       if (primes[primes.length-1] == n) {
          primeFactors.add(n);
       } else {
    
          int max = primes.length - 1;
    
          for (int i=max; i>=0; i--) {
             primeFactors.add(primes[i]);
             if (testPrimeFactor(n, primes[i], primes, i, primeFactors)) {
                break;  // we found our solution
             }
             primeFactors.clear();
          }
       }
    
       return primeFactors;
    }
    
    /**
     * Recursive method initially called by findPrimeFactors(n, g)
     */
    static private boolean testPrimeFactor(int n, int v, int[] primes, int index, List<Integer> factors) {
       int v2 = v * primes[index];
    
       if (v2 == n) {
          factors.add(primes[index]);
          return true;
       } else if (v2 > n) {
          if (index > 0) {
             return testPrimeFactor(n, v, primes, index-1, factors);
          } else {
             return false;
          }
       } else {
          while (index > 0) {
             factors.add(primes[index]);
    
             if (testPrimeFactor(n, v2, primes, index, factors)) {
                return true;
             }
    
             factors.remove(factors.size()-1);   // no good, remove added prime
             v2 = v * primes[--index];
          }
          return false;   // at this point, we are still below n... so no good
       }
    }
    

    最后,我们的测试用例:

    int n = 1025;
    SundaramSievePrimeGenerator generator = new SundaramSievePrimeGenerator();
    
    List<Integer> factors = findPrimeFactors(n, generator);
    
    if (factors.isEmpty()) {
       System.out.println("No prime factors found for " + n);
    } else {
       System.out.println(n + " is composed of " + factors.size() + " prime factors");
       int v = 1;
       for (int i : factors) {
          v *= i;
          System.out.print(" " + i);
       }
       System.out.println(" = " + v);
    }
    

    例如,上述代码将生成:

    1025 is composed of 3 prime factors
     41 5 5 = 1025
    

    而改变n = 81将产生所需的

    81 is composed of 4 prime factors
     3 3 3 3 = 81